package org.rain.core.querygen.support;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.rain.common.util.Strs;
import org.rain.core.querygen.AbsQueryCondition;
import org.rain.core.querygen.token.Token;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * created by yangtong on 2025/4/6 下午10:49
 * <p>
 * or查询，例如age_or = 1,2,3，可以变成age=1 or age=2 or age=3<p>
 * 可以和like查询配合使用，比如age_or=*1*,*2*,*3* -> age like '%1%' or age like '%2%' or age like '%3%'
 */
@Component
public class OrQueryCondition extends AbsQueryCondition implements Ordered {

    @Autowired
    private List<AbsQueryCondition> conditions;

    @Override
    public Boolean isMatch(Token token) {
        return Strs.isNotEmpty(token.getKey()) && token.getKey().endsWith("_or");
    }

    @Override
    public <T> QueryWrapper<T> genQueryWrapper(QueryWrapper<T> queryWrapper, Token token) {
        //去除掉key后面的"_or"
        String realKey = token.getKey().substring(0, token.getKey().length() - 3);
        token.setKey(realKey);
        return positiveOrNegate(queryWrapper, token);
    }

    @Override
    protected <T> QueryWrapper<T> positive(QueryWrapper<T> queryWrapper, Token token) {
        //将value拆分成多个子value
        String[] subValues = token.getValue().split(",");
        return splicingAnd(queryWrapper, token, subValues);
    }

    @Override
    protected <T> QueryWrapper<T> negate(QueryWrapper<T> queryWrapper, Token token) {
        //将value拆分成多个子value
        String[] subValues = token.getValue().split(",");
        return queryWrapper.not(qw -> splicingAnd(qw, token, subValues));
    }

    //拼接条件
    private <T> QueryWrapper<T> splicingAnd(QueryWrapper<T> queryWrapper, Token token, String[] subValues) {
        return queryWrapper.and(wrapper -> {
            for (String subValue : subValues) {
                Token t = new Token(token.getKey(), token.isPositive(), subValue);
                for (AbsQueryCondition condition : conditions) {
                    if (condition.isMatch(t)) {
                        condition.genQueryWrapper(wrapper.or(), t);
                        break;
                    }
                }
            }
        });
    }

    @Override
    public int getOrder() {
        return Integer.MAX_VALUE;
    }
}
